<?php


namespace App\Imports;

use App\Exceptions\ApiException;
use App\Services\BaseService;
use App\Services\BookCatalogService;
use App\Services\BookTitleService;
use App\Services\CommonService;
use App\Services\ProjectClassifyService;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithColumnLimit;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Events\AfterImport;

/**
 * Class BookCatalogImportA
 * @package App\Imports
 * 下面发现个现象 BookCatalogImportA 如果 implements  SkipsEmptyRows会导致  WithStartRow 失效
 */
class BatchUnitProCatalogImportLY implements ToModel, WithStartRow, WithColumnLimit, WithEvents
{
    protected $partCompanyId;
    protected $projectClassifyId;
    protected $startRow;
    protected $redisExpireTime;
    protected $stop;
    protected $bookTitleInstance;
    protected $bookCatalogInstance;
    protected $archivesNoKey;
    protected $bookTitleIdKey;
    protected $importCountKey;
    protected $linkBtIdsKey;

    /**
     * 如果一个档案号 6秒内出现多次，直接视为一个档案号多页写入数据，不进行覆盖
     */
    public function __construct($partCompanyId, $projectClassifyId, $importCountKey)
    {
        $this->partCompanyId       = $partCompanyId;
        $this->projectClassifyId   = $projectClassifyId;
        $this->importCountKey      = $importCountKey;
        $this->stop                = 0; //0继续读取，1停止读取
        $this->startRow            = 1; //从第几行开始
        $this->bookTitleIdKey      = 'book_title_id:' . $importCountKey;
        $this->archivesNoKey       = 'archives_no:' . $importCountKey;
        $this->linkBtIdsKey        = 'linkBtIdsKey:' . $importCountKey; //这里存放 一个
        $this->redisExpireTime     = 5; //把档案号存起来，如果5秒内出现重复的档案号，直接认为是追加数据，而不是覆盖
        $this->bookTitleInstance   = CommonService::getBookTitleInstance($partCompanyId, $projectClassifyId);
        $this->bookCatalogInstance = CommonService::getBookCatalogInstance($partCompanyId, $projectClassifyId);
    }

    /**
     * 注意：self::cacheBookTitleId($archivesNo); 不可以从 if ...else... 里面拿出来合为一个！
     */
    public function model(array $row)
    {
        if (str_contains(trim($row[0]), '档案号：')) { //第一种格式：有档案号
            $archivesNo = mb_substr(trim($row[0]), 4);
            $archivesNo = format_archives_no(trim($archivesNo));
            self::cacheBookTitleId($archivesNo);
        }
        $title = format_str($row[2]);
        if (!empty($title)) { //视为有数据
            $archivesNo = redis()->get($this->archivesNoKey);
            if (!empty($archivesNo)) {
                $bookTitleId = redis()->get($this->bookTitleIdKey);
                if (empty($bookTitleId)) {
                    throw new ApiException("找不到档案号 {$row[0]}！格式存在错误");
                }
                if (is_numeric($row[0])) { //只写入序号为数字的例如 1、2、3....
                    redis()->incr($this->importCountKey);
                    $pageNum = (new BaseService())->formatSerialNo($row[3], 2);
                    $this->bookCatalogInstance->insert([
                        'book_title_id' => $bookTitleId,
                        'serial_no'     => to_int($row[0]),     //序号
                        'file_number'   => format_str($row[1]), //图号或文件编号
                        'title'         => $title,              //件材料题名
                        'page_num'      => $pageNum ?? 1,       //张次
                        'remark'        => format_str($row[4]), //备注
                        'created_at'    => now(),
                        'updated_at'    => now(),
                        'creator_id'    => user_id(),
                    ]);
                }
            }
        }
    }

    /**
     * 使用档案号查询案卷目录id，查出后进行缓存
     */
    private function cacheBookTitleId($archivesNo)
    {
        if ($archivesNo && (redis()->get($this->archivesNoKey) != $archivesNo)) { //如果10秒内档案号一致，继续写入，不覆盖

            $projectClassify = ProjectClassifyService::getProjectClassifyArrInfo($this->partCompanyId, $archivesNo);  //和项目分类数据进行比对，判断往哪个里面写入
            if ($projectClassify) {
                $this->bookTitleInstance   = CommonService::getBookTitleInstance($this->partCompanyId, $projectClassify['id']);
                $this->bookCatalogInstance = CommonService::getBookCatalogInstance($this->partCompanyId, $projectClassify['id']);
                $bookTitleId               = $this->bookTitleInstance->where('archives_no', $archivesNo)->value('id');

                $linkBtIdsArr = ['id1' => $this->partCompanyId, 'id2' => $projectClassify['id'], 'id3' => $bookTitleId ];
                redis()->sadd($this->linkBtIdsKey, json_encode($linkBtIdsArr));

                if (empty($bookTitleId)) {
                    throw new ApiException('找不到档案号：' . $archivesNo . ',档案号必须已存在于系统。或者是否有隐藏的sheet表格？请尝试新建个xlsx文件,并复制所需数据 或者 刷新下页面！');
                }
                redis()->setex($this->archivesNoKey, $this->redisExpireTime, $archivesNo); //把档案号存起来
                redis()->setex($this->bookTitleIdKey, $this->redisExpireTime, $bookTitleId); //暂存案卷目录id
                $this->bookTitleInstance->where('id', $bookTitleId)->update(['is_have_data' => 1, 'is_need_check' => 1]); //更新为没有数据,需要检查
                $catalogIds = $this->bookCatalogInstance->where('book_title_id', $bookTitleId)->pluck('id');
                if ($catalogIds->isNotEmpty()) { //把卷内PDF也删了
                    $catalogIds = $catalogIds->toArray();
                    (new BookCatalogService())->delCatalogPdf($this->partCompanyId, $this->projectClassifyId, $catalogIds);
                }
                $this->bookCatalogInstance->where('book_title_id', $bookTitleId)->delete();
            }
        }
    }

    /**
     * 直接过滤表头，第一块数据含表头
     *
     * @return int
     */
    public function startRow(): int
    {
        return $this->startRow;
    }

    /**
     * @return string
     * @author: lxk
     * @date: 2023/9/12 17:23
     */
    public function endColumn(): string
    {
        return 'G';
    }

    /**
     * excel导入完毕后执行的方法
     *
     * @return \Closure[]
     * @author: lxk
     * @date: 2024-11-16 14:47
     */
    public function registerEvents(): array
    {
        $linkBtIdsKey = $this->linkBtIdsKey;
        return [
            AfterImport::class => function () use ($linkBtIdsKey) {
                $linkBtIdArrJsons = redis()->smembers($linkBtIdsKey);
                foreach ($linkBtIdArrJsons as $linkBtIdArrJson) {
                    $linkBtIdArr = json_decode($linkBtIdArrJson, true);
                    BookTitleService::updateCatalogCount($linkBtIdArr['id1'], $linkBtIdArr['id2'], $linkBtIdArr['id3']);
                }
                redis()->del($linkBtIdsKey);
            }
        ];
    }


}
